/**
  ******************************************************************************
  * @author     Chris
  * @since      2024/6/14 22:34
  *
  * @file       hd_led.c
  * @brief      LED Hardware Driver.
  *
  * @note       This file contains the hardware driver for the LED.
  *
  * @warning    The current flowing through the LED cannot exceed 25 mA. It's
  *             better to add a register with LED.
  ******************************************************************************
  * Change Logs:
  *   Date           Author       Notes
  *   2024/6/14     Chris        the first version
  *
  ******************************************************************************
  */

#include <stm32f4xx_ll_gpio.h>
#include "hd_led.h"

/**
 * @brief   LED（Light Emitting Diode，发光二极管）初始化
 * @note    GPIO 配置为上拉输出模式即可。
 * @param   this const LED
 * @retval  无
 */
static void LED_init(const LED *this) {
    this->gpio->Mode = LL_GPIO_MODE_OUTPUT;
    this->gpio->Speed = LL_GPIO_SPEED_FREQ_HIGH;
    this->gpio->OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    this->gpio->Pull = LL_GPIO_PULL_UP;
    this->gpio->Alternate = LL_GPIO_AF_0;

    this->gpio->init(this->gpio);
}

/**
 * @brief   LED（Light Emitting Diode，发光二极管）点亮
 *
 * @note    GPIO 配置为上拉输出模式即可。
 * @param   无
 * @retval  无
 */
static void LED_on(const LED *this) {
    this->gpio->GPIOx->BSRR = this->gpio->Pin;
}

/**
 * @brief   LED（Light Emitting Diode，发光二极管）关闭
 *
 * @note    GPIO 配置为上拉输出模式即可。
 * @param   无
 * @retval  无
 */
static void LED_off(const LED *this) {
    this->gpio->GPIOx->BSRR = this->gpio->Pin << 16;
}

/**
 * @brief   LED（Light Emitting Diode，发光二极管）翻转
 *
 * @note    通过寄存器的方式实现 GPIO 口的翻转
 * @param   无
 * @retval  无
 */
static void LED_turn(const LED *this) {
    LL_GPIO_TogglePin(this->gpio->GPIOx, this->gpio->Pin);
}

static LED *build(GPIO *gpio) {
    LED *led = malloc(sizeof(LED));

    Driver_add(led, GEN_PERM);

    led->gpio = gpio;
    led->init = &LED_init;
    led->on   = &LED_on;
    led->off  = &LED_off;
    led->turn = &LED_turn;

    return led;
}

const struct LEDClass LEDBuilder = {.build = &build};
